package hehe.aop;

import hehe.aop.annotation.AopAnnotation;
import hehe.aop.base.*;
import java.util.*;

/**
 * 切面管理类
 *<B>说明：</B>
 *<pre>
 * 切面包含拦截器,钩子
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class AopManager
{


    public static AopManager aopManager = null;

    /**
     * 切面列表
     *<B>说明：</B>
     *<pre>
     *  ['表达式',Aspect]
     *</pre>
     */
    protected Map<String,Aspect> aspects = new HashMap<>();

    /**
     * 事件列表
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected Map<String,Event> events = new HashMap<>();

    /**
     * 通知点表达式
     *<B>说明：</B>
     *<pre>
     *  expression 表达式一般方法路径，支持正则表表达式
     *</pre>
     */
    protected Set<String> aspectsExpression = new HashSet<>();

    public AopManager()
    {
        AopManager.aopManager = this;
    }

    public static AopManager getAopManager()
    {
        if (AopManager.aopManager == null) {
            new AopManager();
        }

        return AopManager.aopManager;
    }

    /**
     * 绑定事件与行为
     *<B>说明：</B>
     *<pre>
     *  ['表达式',]
     *</pre>
     * @param behaviors 行为
     * @param advice　事件名称
     * @param expression　表达式
     */
    public void addAspect(Class<? extends Behavior>[] behaviors,String advice,String expression)
    {
        if (this.aspects.containsKey(expression)) {
            this.aspects.get(expression).addAdviceBehavior(advice,behaviors);
        } else {
            Aspect aspect = new Aspect();
            aspect.addAdviceBehavior(advice,behaviors);
            this.aspects.put(expression,aspect);
        }
    }

    /**
     * 获取表达式下的所有行为
     *<B>说明：</B>
     *<pre>
     *  包括before,after
     *</pre>
     */
    public Aspect getAspect(String expression)
    {
        // key/value 方式
        if (this.aspects.containsKey(expression)) {
            return this.aspects.get(expression);
        }

        // 判断是否有advice
        String adviceExpression = findAdvice(expression);
        if (adviceExpression != null) {
            return this.aspects.get(adviceExpression);
        }

        return null;
    }

    /**
     * 是否有通知
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param expression 表达式
     */
    protected String findAdvice(String expression)
    {
        // 迭代
        Iterator advices = this.aspectsExpression.iterator();
        String adviceExpression;
        while(advices.hasNext()) {
            adviceExpression = (String)advices.next();
        }

        return null;
    }

    /**
     * 执行拦截器
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void triggerInterceptor(Aspect aspect, String advice, Object target)
    {

        if (aspect == null || !aspect.hasAdvice(advice)) {
            return;
        }

        Event event = aspect.getAdviceEvent(advice);
        if (event != null) {
            event.trigger(target,null);
        }
    }

    /**
     * 绑定事件
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public void addEventBehavior(String eventName,Class<? extends Behavior> behavior)
    {
        if (this.events.containsKey(eventName)) {
            this.events.get(eventName).addBehavior(behavior);
        } else {
            Event event = new Event();
            event.addBehavior(behavior);
            this.events.put(eventName,event);
        }
    }

    /**
     * 触发事件
     *<B>说明：</B>
     *<pre>
     *  按顺序执行事件的行为
     *</pre>
     * @param eventName 事件名称
     */
    public void triggerEvent(String eventName,Map<String,Object> attrs,Object target)
    {
        if (this.events.containsKey(eventName)) {
            Event event = this.events.get(eventName);
            event.trigger(target,attrs);
        }
    }

    /**
     * 格式化表达式
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String formatExpression(String expression)
    {
        return expression;
    }

    /**
     * 获取代理对象
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Object getProxy(Object target)
    {
        // 解析注解
        try {
            AopAnnotation.parseAnnotation(target.getClass());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return  this.createProxy(target);
    }

    /**
     * 创建代理对象
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected  Object createProxy(Object target)
    {
        ProxyCallback proxyCallback = new ProxyCallback(target);
        Proxy proxy = new Proxy(target,proxyCallback);

        return proxy.createProxy();
    }

}
